사실 요즘은 자체적으로 이렇게 동영상 플레이어를 구현하는 것이 아니라,
유튜브와 같은 플랫폼에 이미 업로드 되어있는 영상을 불러오는 형식을 더 자주 사용하기 때문에, 실용적인 챕터일까? 라는 생각을 하기도 했다.
하지만…
JS를 통해 CSS적인 요소를 컨트롤 하는 부분과 valueChange를 하는 등의 연습은 큰 도움이 됐던 것 같다.
로직
- 다양한 객체들 const로 정의
- 이벤트 리스너 (재생버튼, 프로그레스바, 볼륨바, 속도바, 스킵버튼)
- 재생 기능과 CSS 제어
- 프로그레스바 구현
- 볼륨 컨트롤 구현
- 속도 설정 구현
- 스킵버튼 구현
Const!!
💡 이번 챕터에선 정의해줘야 할 객체들이 많다….
1 2 3 4 5 6 7
| const player = document.querySelector('.player'); const video = player.querySelector('.viewer'); const toggle = player.querySelector('.toggle'); const progress = player.querySelector('.progress'); const progressBar = player.querySelector('.progress__filled'); const skipButtons = player.querySelectorAll('[data-skip]'); const ranges = player.querySelectorAll('.player__slider');
|
이벤트리스너
💡 구현해야 할 기능들이 많기 때문에… 이벤트 또한 역시나 많다…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| toggle.addEventListener('click', pause); toggle.addEventListener('click', updateButton);
video.addEventListener('click', pause); video.addEventListener('click', updateButton); video.addEventListener('timeupdate', handleProgress);
ranges.forEach((range) => range.addEventListener('mousemove', valueChange)); ranges.forEach((range) => range.addEventListener('change', valueChange));
skipButtons.forEach((button) => button.addEventListener('click', skip));
|
재생과 버튼 업데이트
💡 재생 버튼을 누르면 재생이 되고, 버튼 아이콘도 변경되어야 한다.
필자는 if문을 쓰는게 더 쉽고 간편할 것 같아서…
if문을 통해 재생 및 일시정지, 그리고 재생버튼 업데이트 기능을 구현해봤다.
❗ 재생버튼 뿐만 아니라, 유튜브와 같이 비디오 플레이어 화면을 클릭했을 때도 재생 또는 일시정지가 될 수 있도록 구현하기 위해 pause함수가 video와 toggle에도 작동할 수 있도록 이벤트리스너를 작성했다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function pause() { if (video.paused) { video.play(); } else { video.pause(); } }
function updateButton() { if (video.paused) { toggle.textContent = '►'; } else { toggle.textContent = '❚ ❚'; } }
|
그 외 기능들
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function valueChange() { video[this.name] = this.value; }
function skip() { video.currentTime += parseFloat(this.dataset.skip); }
function scrub(e) { video.currentTime = (e.offsetX / progress.offsetWidth) * video.duration; }
function handleProgress() { const percent = (video.currentTime / video.duration) * 100; progressBar.style.flexBasis = `${percent}%`; }
|
최종 완성 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| const player = document.querySelector('.player'); const video = player.querySelector('.viewer'); const toggle = player.querySelector('.toggle'); const progress = player.querySelector('.progress'); const progressBar = player.querySelector('.progress__filled'); const skipButtons = player.querySelectorAll('[data-skip]'); const ranges = player.querySelectorAll('.player__slider');
function pause() { if (video.paused) { video.play(); } else { video.pause(); } }
function updateButton() { if (video.paused) { toggle.textContent = '►'; } else { toggle.textContent = '❚ ❚'; } }
function valueChange() { video[this.name] = this.value; }
function skip() { video.currentTime += parseFloat(this.dataset.skip); }
function scrub(e) { video.currentTime = (e.offsetX / progress.offsetWidth) * video.duration; }
function handleProgress() { const percent = (video.currentTime / video.duration) * 100; progressBar.style.flexBasis = `${percent}%`; }
toggle.addEventListener('click', pause); toggle.addEventListener('click', updateButton);
video.addEventListener('click', pause); video.addEventListener('click', updateButton); video.addEventListener('timeupdate', handleProgress);
ranges.forEach((range) => range.addEventListener('mousemove', valueChange)); ranges.forEach((range) => range.addEventListener('change', valueChange));
skipButtons.forEach((button) => button.addEventListener('click', skip));
let mousedown = false; progress.addEventListener('click', scrub); progress.addEventListener('mouseup', (e) => mousedown && scrub(e)); progress.addEventListener('mousedown', () => (mousedown = true)); progress.addEventListener('mousemove', () => (mousedown = false));
|